package com.my.spring.framework.beans.support;

import com.my.spring.framework.beans.config.MyBeanDefinition;
import com.my.spring.framework.utils.BeanNameUtil;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

public class MyBeanDefinitionReader {
    private static final String SCAN_PACKAGE = "scanPackage";

    private Properties config = new Properties();

    private List<String> registryBeanClasses = new ArrayList<>();

    public MyBeanDefinitionReader(String... configLocations) {
        InputStream is = getClass().getClassLoader().getResourceAsStream(configLocations[0]
                .replace("classpath:", ""));
        try {
            config.load(is);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        doScan(config.getProperty(SCAN_PACKAGE));
    }

    private void doScan(String scanPackage) {
        // URL url = getClass().getClassLoader().getResource("/" + scanPackage.replaceAll("\\.", "/"));
        URL url = getClass().getResource("/" + scanPackage.replaceAll("\\.", "/"));
        File classPath = new File(url.getFile());
        for (File file : classPath.listFiles()) {
            if (file.isDirectory()) {
                doScan(scanPackage + "." + file.getName());
            } else {
                if (!file.getName().endsWith(".class")) {
                    continue;
                }
                String className = scanPackage + "." + file.getName().replaceAll(".class", "");
                registryBeanClasses.add(className);
            }
        }
    }

    public Properties getConfig() {
        return config;
    }

    public List<MyBeanDefinition> loadBeanDefinitions() {
        List<MyBeanDefinition> result = new ArrayList<>();
        try {
            for (String className : registryBeanClasses) {
                Class<?> beanClass = Class.forName(className);
                if (beanClass.isInterface()) {
                    continue;
                }

                result.add(doCreateBeanDefinition(BeanNameUtil.getBeanName(beanClass), className));

                Class<?>[] interfaces = beanClass.getInterfaces();
                for (Class<?> i : interfaces) {
                    result.add(doCreateBeanDefinition(i.getName(), className));
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    private MyBeanDefinition doCreateBeanDefinition (String beanName, String className) {
        MyBeanDefinition beanDefinition = new MyBeanDefinition();
        beanDefinition.setBeanClassName(className);
        beanDefinition.setFactoryBeanName(beanName);
        return beanDefinition;
    }
}
